﻿using System;
using System.ServiceModel;
using Framework.Core;
using Framework.Remoting.Client;
using Framework.Remoting.Conventions;
using Framework.Tests.Wcf.Client.ServiceDefinition;
using Rhino.Mocks;
using Rhino.Mocks.Interfaces;
using Xunit;

namespace Framework.Tests.Wcf.Client
{
    extern alias castlecore;

    public class RetryingTest
    {
        private readonly castlecore::Castle.DynamicProxy.IInterceptor target;
        private const EnvMode EnvMode = Framework.Core.EnvMode.Prod;

        private readonly WcfServiceInfo wcfServiceInfo = new WcfServiceInfo(new NetTcpBinding(),
                                                                            new Uri("net.tcp://pouet.org"));

        private readonly MockRepository mockRepository = new MockRepository();

        public RetryingTest()
        {
            invocationMock = mockRepository.StrictMock<castlecore::Castle.DynamicProxy.IInvocation>();
            requestMock = mockRepository.StrictMock<IRequest>();
            var wcfServiceInfoFactoryMock = mockRepository.StrictMock<IWcfServiceInfoFactory>();
            
            wcfServiceInfoFactoryMock.Expect(x => x.Create<IContract>(EnvMode)).Return(wcfServiceInfo);
            invocationMock.Expect(x => x.ReturnValue).PropertyBehavior();
            mockRepository.ReplayAll();

            target = new WcfInterceptor<IContract>(EnvMode, requestMock, wcfServiceInfoFactoryMock);
        }

        private readonly castlecore::Castle.DynamicProxy.IInvocation invocationMock;

        private readonly IRequest requestMock;

        [Fact]
        public void When_CommunicationException_occur_Then_retry_to_send()
        {
            var methodInfoExpect = MockInvocation();
            methodInfoExpect.Throw(new CommunicationException());
            MockInvocation();
            mockRepository.ReplayAll();
            target.Intercept(invocationMock);
            mockRepository.VerifyAll();
        }

        private IMethodOptions<object> MockInvocation()
        {
            return requestMock.Expect(x => x.Invoke((Func<IContract, object>) null, null)).IgnoreArguments().Return(new object());
        }
    }
}